/** * Java Diagram Package; An extremely flexible and fast multipurpose diagram component for Swing. Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package diagram; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * @class DefaultDiagramModel * * @author Eric Crahen * @date 08-20-2001 * @version 1.0 * * The DefaultDiagramModel implements a working DiagramModel that is * capable of storing and removing various Figures, but not associating * data with those Figures. * * Serialization of the default model is accoomplished by through a simple * format. A table of all Figures that are a part of this model is written, * followed by a table of extra information for each Figure. This allows * shared objects (such as Link endpoints and some compound Figures) to be * handled correctly (no duplicates are created just because a Figure is * references several times). * * Derivatives of this class should override the writeExternal(Figure, ...) * and readExternal(Figure, ...) methods to customize what extra * information is store for each Figure. * * * TODO: Update the externalization methods to handle links to Figures not * members of the Model. */ public class DefaultDiagramModel extends AbstractDiagramModel implements Serializable { private static FigureComparator comparator = new FigureComparator(); private ArrayList figures = new ArrayList(); private HashMap valueMap = new HashMap(); /** * * @param Figure */ public void add(Figure fig) { if(!figures.contains(fig)) { figures.add(fig); fireFigureAdded(fig); } } /** * * @param Figure */ public void remove(Figure fig) { if(figures.contains(fig)) { figures.remove(fig); fireFigureRemoved(fig); } } /** * Remove all figures from the model */ public void clear() { while(!figures.isEmpty()) fireFigureRemoved((Figure)figures.remove(figures.size()-1)); valueMap.clear(); } /** * Get the number of Figures in this model */ public int size() { return figures.size(); } /** * * @return Iterator */ public Iterator iterator() { return new RepeatingIterator(figures); } /** * Associate a value with a Figure * * @param Figure * @param Object */ public void setValue(Figure figure, Object value) { valueMap.put(figure, value); } /** * Get value associated with a Figure * * @param Figure * @return Object */ public Object getValue(Figure figure) { return valueMap.get(figure); } /** * @class RepeatingIterator * * Iterator implementation that will walk over the elements of some * List. Once the end of the list is reached, and has been tested once * with hasNext() returning false the Iterator is reset. It can then * walk over the set of Objects in the List once again. */ protected class RepeatingIterator implements Iterator { private List list; private int index; public RepeatingIterator(List list) { this.list = list; this.index = -1; } public boolean hasNext() { if(++index == list.size()) { index = -1; return false; } return true; } public Object next() { return list.get(index); } public void remove() {} } /** * Get all selected items. The items returned will be pruned by * the arrays element class if any. Passing a Figure[] array would return * all Figure classes & subclasses in the selection model. * * @param Object[] - avoid allocating a new array * * @return Object[] */ public Object[] toArray(Object[] a) { Class itemClass = (a == null) ? Object.class : a.getClass().getComponentType(); if(itemClass == Object.class) return figures.toArray(a); // New array needed, pick a decent element class int len = figures.size(); if(a.length < len) a = (Object[])java.lang.reflect.Array.newInstance(itemClass, len); // Copy by class int n = 0; for(int i=0; i < len; i++) { Object o = figures.get(i); Class c = o.getClass(); if(c == itemClass || itemClass.isAssignableFrom(c)) a[n++] = o; } // Null terminate if(n < a.length) java.util.Arrays.fill(a, n, a.length, null); return a; } }